/*

*/

#ifndef CBRIDGE_H
#define CBRIDGE_H

#include <arpa/inet.h>
#include <netinet/in.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>

#include <qextserialport.h>
#include <mavlink.h>
#include <QtDebug>
#include <math.h>
#include <QBitArray>

#include "MK_v0.24b_NAVI_structs.h"
#include "MK_v0.82a_FC_structs.h"

#define MAX_TX_BUFFER 1000
#define MAX_RX_BUFFER 1000

#define ANY_ADDRESS 0
#define FC_ADDRESS 1
#define NC_ADDRESS 2
#define MK3MAG_ADDRESS 3
#define MKGPS_ADDRESS 4

#define SYSTEM_ID 113
#define COMP_SYSTEM_ID 255
#define COMP_COMPONENT_ID 0

#define MK_OSD_INTERVAL 25
#define MK_OSD_FACTOR 7
#define MK_OSD_STOP 1   //1: means stop OSD while WP list send, 0: continue with OSD while WP list send
//#define TIMER_SERIAL_INTERVAL 10
//wait WATCHDOG_COUNTER_LIMIT*TIMER_HEARTBEAT_INTERVAL milisec before error msg
//#define TIMER_HEARTBEAT_INTERVAL 2000
#define WATCHDOG_COUNTER_LIMIT 2
//in case HeartBeat is to be automatic- this define should be a comment
#define WATCHDOG_OFF

#define PI 3.141592654
#define SRV_IP "127.0.0.1"

#define FULL_CAPACITY 2650
#define SAFTY_CAPACITY (FULL_CAPACITY * 0.15)
#define FULL_VOLTAGE 111  //[0.1 v]
#define MAGIC_TIME_INTERVAL 500

#define COMMAND_ACCEPTED_N_EXECUTED  0
#define COMMAND_TEMPORARY_REJECTED   1
#define COMMAND_PERMANENTLY_DENIED   2
#define COMMAND_UNKNOWEN_UNSUPPORTED 3
#define COMMAND_CONFIRMATION_NEEDED  4

#define CRITICAL_FAULT 255
#define INFO_MESSEGE 0

#define HOME_TOLERANCE_RADIUS 10
#define HOME_HOLD_TIME 250 //time in seconds to stay in HOME position
#define MAV_ACTION_DENIED 0
#define MAV_ACTION_CONFIRMED 1

class CBridge : public QObject
{
    Q_OBJECT

    private:

    void PrintFlags(uint8_t FCStatusFlags, uint8_t FCStatusFlags2, uint8_t NCFlags);

    //Global variable of RC_Quality cause it should be sent in two differnt messges
    uint8_t RC_Q;

    //Global Variables of MK Home
    int32_t home_alt;
    int32_t home_lat;
    int32_t home_long;
    int8_t  home_status;

    //Gloabl variable of Full Capacity of MK battary
    int fullCapacity;

    long CRC_ok;
    long CRC_fail;

    static void * Serial_Receiver_Thread(void* arg);
    pthread_t Serial_Receiver_Thread_ID;
    static void * UDP_Receiver_Thread(void* arg);
    pthread_t UDP_Receiver_Thread_ID;
    static void *HeartBeat_Thread(void* arg);
    pthread_t HeartBeat_Thread_ID;

    struct sockaddr_in si_other;
    int socket_id;
    int slen;

    quint16 receiver_port;
    quint16 sender_port;

    QextSerialPort *serial_port;
    pthread_mutex_t SuspendMutex;

    // Buffers
    char serial_tx_buffer[MAX_TX_BUFFER];
    QByteArray serial_rx_buffer;
    char udp_tx_buffer[MAX_TX_BUFFER];
    char udp_rx_buffer[MAX_RX_BUFFER];
    mavlink_message_t mavlink_msg_from_qgc;
    mavlink_message_t mavlink_msg_to_qgc;

    // QGC (UDP) --> (SERIAL) MK
    void QGC2MK(mavlink_message_t msg);
    void sendMikroKopterMsg(unsigned char cmd,unsigned char address, unsigned char args_no, ...);
    void addCRC(unsigned int current_length);
    void SendWaypoint2MK(mavlink_message_t msg);
    void clear_MK_WP();

    // (SERIAL) MK --> QGC (UDP)
    void processMikroKopterCommand(QByteArray command);
    bool checkRxCRC(unsigned int current_length);
    QByteArray decode64(QByteArray command);

    // Global variables for wp managment
    int total_WP; // Recevied from WAYPOINT_COUNT
    int current_WP; // increased after sending new WAYPOINT_REQUEST
    int CurrentOSDInterval;
    int stop_OSD;
	int first_read;

    //(SERIAL) MK
    void readPendingSerialData();

    // Global variables for WatchDog counter
    int WatchDog_Counter;

    //Timer Event
    void Timer_Heartbeat_Tick ();

    public:
    CBridge(quint16 _receiver_port, quint16 _sender_port, const char *_serial_port_name,int _fullCapacity);
    ~CBridge();

    // Commands without parallel command in MavLink
    void request_MK_Debug (uint8_t AutoSendInterval);
    void request_MK_OSD (uint8_t AutoSendInterval);
    void request_MK_version(int slave_address);

    void redirect_UART(int slave_address);
    void SendMagicCode();

    void StartListening();
    void PrintLoss();

    void request_MK_PPM_Channels();
    void request_MK_Reset ();
    bool EnablePrintFlags;
    void Goto(int address);

    // global variable holding current MK commponent address.
    int CurrentUARTAddress;


};

#endif // CBRIDGE_H
